package com.jtsoftware.servlet;

import java.io.IOException;
import java.lang.reflect.Method;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import com.jtsoftware.utils.JSONSerializer;


public abstract class JavaScriptRpcServlet extends HttpServlet {
	HttpServletRequest request;
	HttpServletResponse response;

	final public void doGet(HttpServletRequest req, HttpServletResponse res)
	throws ServletException, IOException {
		this.request = req;
		this.response = res;
		
		response.setContentType("text/plain");		
		response.setHeader("Cache-Control", "no-cache");
		
		if(!authenticated(req)) return;		
		
		String servletPath = request.getServletPath();
		String pathInfo = request.getPathInfo();
		int lastIndexOf = servletPath.lastIndexOf('/');

		String input = request.getParameter("input");

		String methodName = pathInfo.substring(lastIndexOf+1);
		
		if(methodName.length() < 1) throw new ServletException("No method: " + 
				methodName + " in PathInfo: " + pathInfo);

		Integer id = Integer.parseInt(input);
		String result = executeAndSerialize(methodName,id);
		response.getWriter().write(result);

	}

	final public void doPost(HttpServletRequest request, HttpServletResponse response)
	throws ServletException, IOException {
		doGet(request,response);
	}

	final private String executeAndSerialize(String methodName,int id) throws IOException {
		Object result;
		Method method;
		Class[] object = {int.class};
		Object[] ints = {id};
		if(methodName.equals("executeAndSerialize")||methodName.equals("wait")) 
			throw new ServletSecurityException("Non-allowed Method");
		
		try {
			method = this.getClass().getMethod(methodName, object);
			result = method.invoke(this, ints);
		} catch(Exception e) {
			response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
			e.printStackTrace();
			return "";
		}
		JSONSerializer jsonSerializer = new JSONSerializer();
		String json = jsonSerializer.serialize(result);
		String jsonCount = jsonSerializer.getCount();
		// for some reason won't serialize without () around the JSON
		return "([{"+ jsonCount + "},"+ json + "])";


	}

	final private boolean authenticated(HttpServletRequest r) throws ServletSecurityException {
		HttpSession session = r.getSession();
		UserObject user = (UserObject)session.getAttribute("user");
		
		if(user == null) { 
			this.response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
			return false;
		}
		
		Field permissionField;
		Object p = null;
		try {
			permissionField = this.getClass().getField("PERMISSION");
			p = permissionField.get(this);
		} catch (Exception e) {

		} 

		if(p!=null && !user.hasPermission((Permission)p)) {
			this.response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
			return false;
		}
		
		return true;

	}

	public class ServletSecurityException extends RuntimeException {
		public ServletSecurityException(Throwable e) {
			super(e);
		}
		public ServletSecurityException(String msg) {
			super(msg);
		}

	}

}
